package kr.couponplay.android.domain.deal;

import java.util.List;

import kr.couponplay.android.ApiUrl;
import kr.couponplay.android.AppContext;
import kr.couponplay.android.Constants;
import kr.couponplay.android.domain.AppContextAware;
import kr.couponplay.android.domain.DataContext;
import kr.couponplay.android.domain.FileCacheAware;
import kr.couponplay.android.domain.LastUpdateTimeAware;
import kr.couponplay.android.support.LocationUtils;
import kr.couponplay.android.support.StringUtils;
import kr.couponplay.android.support.cache.DataFileCacheManager;
import kr.couponplay.android.support.cache.FileCache;

import org.json.JSONArray;
import org.json.JSONObject;

import android.content.Context;
import android.location.Location;
import android.util.Log;

public class DealFinder implements AppContextAware, FileCacheAware, LastUpdateTimeAware {
	private long lastUpdateTime;
	private Context applicationContext;
	private DataFileCacheManager cacheManager;
	
	private QueryMaker queryMaker = new QueryMaker();
	private DealDao dealDao = new DealDao();
	private DealJsonParser parser = new DealJsonParser();
	
	public DealList search(String query, int offset) {
		String sid = AppContext.getSid(applicationContext);
		String queryParams = queryMaker.baseQuery(sid, 0, 0, query, offset);
		String url = ApiUrl.searchUrl + queryParams;

		try {
			String jsonString = dealDao.search(url);
			JSONArray jsonDealData = new JSONObject(jsonString).getJSONArray("deals");
			List<Deal> deals = parser.makeDealList(sid, jsonDealData);
			DataContext.lastSearchDealSize = deals.size();
			return new DealList(query, deals);
		} catch (Exception e) {
			Log.e(Constants.TAG, e.getMessage(), e);
			throw new IllegalStateException(e.getMessage(), e);
		}
	}

	public DealListResult selectAllDealList(int mainCategoryId, int subCategoryId, int offset) {
		String sid = AppContext.getSid(applicationContext);
		Location location = LocationUtils.getMyLocation(applicationContext);
		String url = ApiUrl.allDealListUrl + queryMaker.baseQuery(sid, mainCategoryId, subCategoryId, null, offset);
		String locationUrl = queryMaker.locationQuery(url, location);
		String cacheKey = AppContext.getLastUpdatedTime(applicationContext) + "-" + url;
		
		try {
			String data = cacheManager.get(cacheKey);
			if (StringUtils.isEmpty(data)) {
				data = dealDao.selectAllDealList(locationUrl);
				cacheManager.put(cacheKey, data);
			}
			
			JSONArray categoryDealsJson = new JSONObject(data).getJSONArray("categoryDeals");
			JSONArray newDealsJson = new JSONObject(data).getJSONArray("newDeals");
			JSONArray endDealsJson = new JSONObject(data).getJSONArray("endDeals");
			JSONArray freeDealsJson = new JSONObject(data).getJSONArray("freeDeals");
			
			List<Deal> categoryDeals = parser.makeDealList(sid, categoryDealsJson);
			List<Deal> newDeals = parser.makeDealList(sid, newDealsJson);
			List<Deal> endDeals = parser.makeDealList(sid, endDealsJson);
			List<Deal> freeDeals = parser.makeDealList(sid, freeDealsJson);
			
			DataContext.lastCategoryDealSize = categoryDeals.size();
			DataContext.lastNewDealSize = newDeals.size();
			DataContext.lastEndDealSize = endDeals.size();
			DataContext.lastFreeDealSize = freeDeals.size();
			return new DealListResult(categoryDeals, newDeals, endDeals, freeDeals);
		} catch (Exception e) {
			Log.e(Constants.TAG, e.getMessage(), e);
			cacheManager.remove(cacheKey);
			throw new IllegalStateException(e.getMessage(), e);
		}
	}
	
	public List<Deal> selectCategoryDealList(int mainCategoryId, int subCategoryId, int offset) {
		String sid = AppContext.getSid(applicationContext);
		Location location = LocationUtils.getMyLocation(applicationContext);
		String queryParams = queryMaker.baseQuery(sid, mainCategoryId, subCategoryId, null, offset);
		String url = ApiUrl.categoryDealListUrl + queryParams;
		String locationUrl = queryMaker.locationQuery(url, location);
		String cacheKey = AppContext.getLastUpdatedTime(applicationContext) + "-" + ApiUrl.categoryDealListUrl + queryParams;

		try {
			String data = cacheManager.get(cacheKey);
			if (StringUtils.isEmpty(data)) {
				data = dealDao.selectCategoryDealList(locationUrl);
				cacheManager.put(cacheKey, data);
			}

			JSONArray categoryDealsJson = new JSONObject(data).getJSONArray("categoryDeals");
			List<Deal> categoryDeals = parser.makeDealList(sid, categoryDealsJson);
			DataContext.lastCategoryDealSize = categoryDeals.size();
			return categoryDeals;
		} catch (Exception e) {
			cacheManager.remove(cacheKey);
			throw new IllegalStateException(e.getMessage(), e);
		}
	}
	
	public List<Deal> selectNewDealList(int mainCategoryId, int subCategoryId, int offset) {
		String sid = AppContext.getSid(applicationContext);
		String queryParams = queryMaker.baseQuery(sid, mainCategoryId, subCategoryId, null, offset);
		String url = ApiUrl.newDealListUrl + queryParams;
		String cacheKey = AppContext.getLastUpdatedTime(applicationContext) + "-" + ApiUrl.newDealListUrl + queryParams;

		try {
			String data = cacheManager.get(cacheKey);
			if (StringUtils.isEmpty(data)) {
				data = dealDao.selectNewDealList(url);
				cacheManager.put(cacheKey, data);
			}
			
			JSONArray newDealsJson = new JSONObject(data).getJSONArray("newDeals");
			List<Deal> newDeals = parser.makeDealList(sid, newDealsJson);
			DataContext.lastNewDealSize = newDeals.size();
			return newDeals;
		} catch (Exception e) {
			cacheManager.remove(cacheKey);
			throw new IllegalStateException(e.getMessage(), e);
		}
	}
	
	public List<Deal> selectEndDealList(int mainCategoryId, int subCategoryId, int offset) {
		String sid = AppContext.getSid(applicationContext);
		String queryParams = queryMaker.baseQuery(sid, mainCategoryId, subCategoryId, null, offset);
		String url = ApiUrl.endDealListUrl + queryParams;
		String cacheKey = AppContext.getLastUpdatedTime(applicationContext) + "-" + ApiUrl.endDealListUrl + queryParams;

		try {
			String data = cacheManager.get(cacheKey);
			if (StringUtils.isEmpty(data)) {
				data = dealDao.selectEndDealList(url);
				cacheManager.put(cacheKey, data);
			}
			
			JSONArray endDealsJson = new JSONObject(data).getJSONArray("endDeals");
			List<Deal> endDeals = parser.makeDealList(sid, endDealsJson);
			DataContext.lastEndDealSize = endDeals.size();
			return endDeals;
		} catch (Exception e) {
			cacheManager.remove(cacheKey);
			throw new IllegalStateException(e.getMessage(), e);
		}
	}	
	
	public List<Deal> selectFreeDealList(int mainCategoryId, int subCategoryId, int offset) {
		String sid = AppContext.getSid(applicationContext);
		String queryParams = queryMaker.baseQuery(sid, mainCategoryId, subCategoryId, null, offset);
		String url = ApiUrl.freeDealListUrl + queryParams;
		String cacheKey = AppContext.getLastUpdatedTime(applicationContext) + "-" + ApiUrl.freeDealListUrl + queryParams;

		try {
			String data = cacheManager.get(cacheKey);
			if (StringUtils.isEmpty(data)) {
				data = dealDao.selectFreeDealList(url);
				cacheManager.put(cacheKey, data);
			}
			
			JSONArray freeDealsJson = new JSONObject(data).getJSONArray("freeDeals");
			List<Deal> freeDeals = parser.makeDealList(sid, freeDealsJson);
			DataContext.lastFreeDealSize = freeDeals.size();
			return freeDeals;
		} catch (Exception e) {
			cacheManager.remove(cacheKey);
			throw new IllegalStateException(e.getMessage(), e);
		}
	}
	
	public DealList selectRecentViewDeals(int offset) {
		String sid = AppContext.getSid(applicationContext);
		String url = ApiUrl.recentClickDealListUrl + "?sid=" + sid + "&offset=" + offset;
		String data = dealDao.selectRecentViewDeals(url);

		try {
			JSONArray jsonArray = new JSONObject(data).getJSONArray("recentClickDeals");
			List<Deal> deals = parser.makeDealList(sid, jsonArray);
			return new DealList(deals.size(), deals);
		} catch (Exception e) {
			throw new IllegalStateException(e.getMessage(), e);
		}
	}
	
	public DealList selectEventDeals(int offset) {
		String sid = AppContext.getSid(applicationContext);
		String url = ApiUrl.eventDealListUrl + "?sid=" + sid + "&offset=" + offset;
		String data = dealDao.selectEventDeals(url);

		try {
			JSONArray jsonArray = new JSONObject(data).getJSONArray("eventDeals");
			List<Deal> deals = parser.makeDealList(sid, jsonArray);
			return new DealList(deals.size(), deals);
		} catch (Exception e) {
			Log.e(Constants.TAG, e.getMessage(), e);
			throw new IllegalStateException(e.getMessage(), e);
		}
	}	

	@Override
	public void setFileCache(FileCache fileCache) {
		cacheManager = new DataFileCacheManager(fileCache, lastUpdateTime);
	}

	@Override
	public void setApplicationContext(Context applicationContext) {
		this.applicationContext = applicationContext;
	}

	@Override
	public void setLastUpdateTime(long lastUpdateTime) {
		this.lastUpdateTime = lastUpdateTime;
	}
}
